package com.ray.project.ndbc;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import com.ray.project.oceanicbuoy.OceanicBuoy;

import java.util.ArrayList;

public class OceanicBuoyDataManager extends DefaultHandler {

    private static final String POSTRSSITEM = "item";
    private static final String POSTPUBLISHEDDATE = "pubDate";
    private static final String POSTTITLE = "title";
    private static final String POSTDESCRIPTION = "description";
    private static final String POSTLINK = "link";
    private static final String POSTGEORSS = "point";

    private static final SimpleDateFormat DATE_FORMAT_VERBOSE = new SimpleDateFormat("MMMM dd',' yyyy hh:mm a z");
    private static final SimpleDateFormat DATE_FORMAT_SHORT = new SimpleDateFormat("EEE',' dd MMM yyyy hh:mm:ss z");

    private final ArrayList<OceanicBuoy> buoys;
    private OceanicBuoy buoy;

    private boolean postItem;
    private boolean postTitle;
    private boolean postPublishedDate;
    private boolean postDescription;
    private boolean postHyperlink;
    private boolean postGeoRss;

    public OceanicBuoyDataManager() {
        this.buoys = new ArrayList<OceanicBuoy>(); 
    }

    @Override
    public void characters(final char ch[], final int start, final int length) {
        String charString = "";
        if (ch != null) {
            charString = new String(ch, start, length);
        }

        if (this.postTitle) {
            this.buoy.setTitle(charString);
        }

        if (this.postPublishedDate) {
            if (charString.contains("UT")) {
                charString = charString.replace("UT", "GMT");
            }
            this.buoy.setDateString(charString);

            // Handle multiple date formats
            Date publishedDate = null;
            try {
                publishedDate = OceanicBuoyDataManager.DATE_FORMAT_VERBOSE.parse(charString);
            } catch (ParseException e) {
                // Ignore
            }
            if (publishedDate == null) {
                try {
                    publishedDate = OceanicBuoyDataManager.DATE_FORMAT_SHORT.parse(charString);
                } catch (ParseException e) {
                    // Ignore
                }
            }
            this.buoy.setDate(publishedDate);
        }

        // The Description element contains data in a non-XML format. This data must
        // be parsed in a manual way. Parsing this data requires the substantial branching
        // coded below.
        if (this.postDescription) {
            this.buoy.setDescription(charString);
            String[] descriptionArray = charString.split("<br />");
            for (String s : descriptionArray) {
                if (s.indexOf("Location:</strong>") != -1) {
                    this.buoy.setLocation(s.substring(s.indexOf("Location:</strong>") + 18, s.length()).trim());
                } else if (s.indexOf("Wind Direction:</strong>") != -1) {
                    this.buoy.setWindDirection(s.substring(s.indexOf("Wind Direction:</strong>") + 24, s.length())
                        .trim().replaceAll("&#176;", ""));
                } else if (s.indexOf("Wind Speed:</strong>") != -1) {
                    this.buoy.setWindSpeed(s.substring(s.indexOf("Wind Speed:</strong>") + 20, s.length()).trim());
                } else if (s.indexOf("Wind Gust:</strong>") != -1) {
                    this.buoy.setWindGustSpeed(s.substring(s.indexOf("Wind Gust:</strong>") + 19, s.length()).trim());
                } else if (s.indexOf("Significant Wave Height:</strong>") != -1) {
                    this.buoy.setWaveHeight(s.substring(s.indexOf("Significant Wave Height:</strong>") + 33, s.length())
                        .trim());
                } else if (s.indexOf("Dominant Wave Period:</strong>") != -1) {
                    this.buoy.setWavePeriod(s.substring(s.indexOf("Dominant Wave Period:</strong>") + 30, s.length())
                        .trim());
                } else if (s.indexOf("Atmospheric Pressure:</strong>") != -1) {
                    this.buoy.setAtmoPressure(s.substring(s.indexOf("Atmospheric Pressure:</strong>") + 30, s.length())
                        .trim());
                } else if (s.indexOf("Pressure Tendency:</strong>") != -1) {
                    this.buoy.setAtmoPressureTendency(s.substring(s.indexOf("Pressure Tendency:</strong>") + 27,
                        s.length()).trim());
                } else if (s.indexOf("Air Temperature:</strong>") != -1) {
                    this.buoy.setAirTemperature(s.substring(s.indexOf("Air Temperature:</strong>") + 25, s.length()).trim()
                        .replaceAll("&#176;", ""));
                } else if (s.indexOf("Water Temperature:</strong>") != -1) {
                    this.buoy.setWaterTemperature(s.substring(s.indexOf("Water Temperature:</strong>") + 27, s.length()).trim()
                        .replaceAll("&#176;", ""));
                }
            }
        }

        if (this.postHyperlink) {
            this.buoy.setLink(charString);
        }

        if (this.postGeoRss) {
            this.buoy.setGeoRssPoint(charString);
        }
    }

    @Override
    public void endDocument() throws SAXException {
    }

    @Override
    public void endElement(final String namespaceURI, final String elementName, final String qName) throws SAXException {
        if (elementName.equals(OceanicBuoyDataManager.POSTRSSITEM)) {
            this.postItem = false;
            this.buoys.add(this.buoy);
        }

        if (this.postItem) {
            if (elementName.equals(OceanicBuoyDataManager.POSTTITLE)) {
                this.postTitle = false;
            } else if (elementName.equals(OceanicBuoyDataManager.POSTPUBLISHEDDATE)) {
                this.postPublishedDate = false;
            } else if (elementName.equals(OceanicBuoyDataManager.POSTDESCRIPTION)) {
                this.postDescription = false;
            } else if (elementName.equals(OceanicBuoyDataManager.POSTLINK)) {
                this.postHyperlink = false;
            } else if (elementName.equals(OceanicBuoyDataManager.POSTGEORSS)) {
                this.postGeoRss = false;
            }
        }
    }

    public ArrayList<OceanicBuoy> getBuoyDataList() {
        return this.buoys;
    }

    @Override
    public void startDocument() throws SAXException {
    }

    @Override
    public void startElement(final String namespaceURI, final String localName, final String qName,
        final Attributes atts) throws SAXException {
        if (localName.equals(OceanicBuoyDataManager.POSTRSSITEM)) {
            this.postItem = true;
            this.buoy = new OceanicBuoy();
        }

        if (this.postItem) {
            if (localName.equals(OceanicBuoyDataManager.POSTTITLE)) {
                this.postTitle = true;
            } else if (localName.equals(OceanicBuoyDataManager.POSTPUBLISHEDDATE)) {
                this.postPublishedDate = true;
            } else if (localName.equals(OceanicBuoyDataManager.POSTDESCRIPTION)) {
                this.postDescription = true;
            } else if (localName.equals(OceanicBuoyDataManager.POSTLINK)) {
                this.postHyperlink = true;
            } else if (localName.equals(OceanicBuoyDataManager.POSTGEORSS)) {
                this.postGeoRss = true;
            }
        }
    }
}
